package com.tool.cn.util;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @author wangzonghui
 * @date 2020年6月10日 下午4:01:59 
 * @Description:ftp客户端工具类
 */
public class FtpUtil {
	
	private static Logger log = LoggerFactory.getLogger(FtpUtil.class);
	
	
	// 客户端数据文件路径
	public static String client_path = "D:\\工作文件\\data\\";
	public static String download = "D:\\工作文件\\data\\";
	
	// 服务器上的存放数据文件路径
	public static String server_path = "/user/hdfs/";
	public static String ftpHost = "172.16.34.160";
	public static String ftpUserName = "hdfs";
	public static String ftpPassword = "hdfs";
	public static int ftpPort = 11110;// 查找路径下的指定txt文件，然后采用FTP上传
	
	public static void main(String[] args) {
		String fileName="20160917083420_rawdata_s1mme.dat";
//		uploadServerByFtp(fileName);
		downloadFtpFile(fileName);
	}
	
	
	/**
	 * 登录ftp
	 * @param ftpHost  主机
	 * @param ftpPort 端口
	 * @param ftpUserName 用户名
	 * @param ftpPassword 密码
	 * @return
	 */
	public static FTPClient getFTPClient(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword) {
		FTPClient ftpClient = null;
		try {
			ftpClient = new FTPClient();
			ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
			ftpClient.login(ftpUserName, ftpPassword);// 登陆FTP服务器
			if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
				log.info("未连接到FTP，用户名或密码错误。");
				ftpClient.disconnect();

				return null;
			} else {
				log.info("FTP连接成功。");
			}
			
			ftpClient.setControlEncoding("UTF-8");
//			ftpClient.enterLocalActiveMode(); // 主动模式
			ftpClient.enterLocalPassiveMode();// 设置被动模式 ，网络环境异常时，使用被动模式。防止服务端找不到路由器后的客户端
			ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); // 设置传输的模式(文本文件|二进制文件),MAGE_FILE_TYPE图片文件
			
		} catch (Exception e) {
			log.info("FTP的端口错误,请正确配置。",e);
		}
		return ftpClient;
	}


	/**
	 * 上传文件到ftp服务器
	 * @param fileNmae 要上传的文件名
	 * @return
	 */
	public static boolean uploadServerByFtp(String fileName) {
		boolean flag = true;
		
		
		File file_name = new File(client_path + fileName);
		if (!file_name.exists()) {
			log.error("No Found File");
			return false;
		}
		
		log.info("File Size:"+file_name.length());
		long one=System.currentTimeMillis();
		FTPClient ftpClient = null;
		
		try {
			// 创建ftp客户端
			ftpClient = getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword);
			
			if(ftpClient==null) {
				return false;
			}
			
			String getfileName = file_name.getName();
			
			long connect=System.currentTimeMillis();
			
			log.info("Connection Time:{}",connect-one);
			
			String server_file_name = server_path + getfileName;

			InputStream input = new FileInputStream(file_name);
			
			OutputStream out = ftpClient.storeFileStream(server_file_name);
			byte[] byteArray = new byte[4096];
			int read = 0;
			while ((read = input.read(byteArray)) != -1) {
				out.write(byteArray, 0, read);
			}
			input.close();
			out.flush();
			out.close();
			ftpClient.logout();
			
			FTPFile[] fileList=ftpClient.listFiles(server_file_name);
			log.info("Uploaded File Size:{}",fileList[0].getSize());
			
			long  upload=System.currentTimeMillis();
			log.info("Upload Time:{} all Time:{}",upload-connect,upload-one);

		} catch (Exception e) {
			flag = false;
			log.error(e.toString(),e);
		} finally {
			if (ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				} catch (IOException ioe) {
					ioe.printStackTrace();
				}
			}
		}
		return flag;
	}
	
	/**
	 * 下载文件
	 * @param fileName
	 */
	public static void downloadFtpFile(String fileName) {
 
		FTPClient ftpClient = null;
		long one=System.currentTimeMillis();
		try {
			ftpClient = getFTPClient(ftpHost, ftpPort, ftpUserName, ftpPassword);
			if(ftpClient==null) {
				return ;
			}

			long connect=System.currentTimeMillis();
			log.info("Connection Time:{}",connect-one);
			
			//对中文文件名进行转码，否则中文名称的文件下载失败
//			String fileNameTemp = new String(fileName.getBytes(LOCAL_CHARSET), SERVER_CHARSET);
//			ftpClient.changeWorkingDirectory(ftpPath);  
			
			String server_file_name = server_path + fileName;
			InputStream retrieveFileStream = ftpClient.retrieveFileStream(server_file_name);
			 
			byte[] input2byte = input2byte(retrieveFileStream);
			byte2File(input2byte, download, fileName);
			
			if(null != retrieveFileStream){
				retrieveFileStream.close();
			}
			
			long  upload=System.currentTimeMillis();
			log.info("Upload Time:{} all Time:{}",upload-connect,upload-one);
		} catch (FileNotFoundException e) {
			log.error("没有找到" + server_path + "文件",e);
		} catch (SocketException e) {
			log.error("连接FTP失败.",e);
		} catch (IOException e) {
			e.printStackTrace();
			log.error("文件读取错误。",e);
		} finally {
			
			if (ftpClient.isConnected()) {
				try {
					//退出登录
					ftpClient.logout();
					//关闭连接
					ftpClient.disconnect(); 
				} catch (IOException e) {
				}
			}
		}
	}
 
	// 将输入流转为byte[]
	public static final byte[] input2byte(InputStream inStream) throws IOException {
		ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
		byte[] buff = new byte[1024];
		int rc = 0;
		while ((rc = inStream.read(buff, 0, 100)) > 0) {
			swapStream.write(buff, 0, rc);
		}
		byte[] in2b = swapStream.toByteArray();
		return in2b;
	}
 
	// 将byte[]转为文件
	public static void byte2File(byte[] buf, String filePath, String fileName) {
		BufferedOutputStream bos = null;
		FileOutputStream fos = null;
		File file = null;
		try {
			File dir = new File(filePath);
			if (!dir.exists() && dir.isDirectory()) {
				dir.mkdirs();
			}
			file = new File(filePath + File.separator + fileName);
			fos = new FileOutputStream(file);
			bos = new BufferedOutputStream(fos);
			bos.write(buf);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 创建多层目录文件，如果有ftp服务器已存在该文件，则不创建，如果无，则创建
	 * @param remote
	 * @param ftpClient
	 * @return
	 */
    public static boolean CreateDirecroty(String remote,FTPClient ftpClient) {
        boolean success = true;
        remote=remote.replace("//", "/");
        String directory = remote + "/";
        
        try {
			if (!directory.equalsIgnoreCase("/") && !changeWorkingDirectory(new String(directory),ftpClient)) {
			    int start = 0;
			    int end = 0;
			    if (directory.startsWith("/")) {
			        start = 1;
			    } else {
			        start = 0;
			    }
			    end = directory.indexOf("/", start);
			    String path = "";
			    String paths = "";
			    while (true) {

			        String subDirectory = new String(remote.substring(start, end).getBytes("GBK"), "iso-8859-1");
			        path = path + "/" + subDirectory;
			        
			        if (!existFile(path,ftpClient)) {  //false 目录不存在
			            if (makeDirectory(subDirectory,ftpClient)) {
			                changeWorkingDirectory(subDirectory,ftpClient);
			            } else {
			                return false;
			            }
			        } else {
			            changeWorkingDirectory(subDirectory,ftpClient);  //切换目录
			        }

			        paths = paths + "/" + subDirectory;
			        start = end + 1;
			        end = directory.indexOf("/", start);
			        // 检查所有目录是否创建完毕
			        if (end <= start) {
			            break;
			        }
			    }
			}
			
		} catch (Exception e) {
			log.error(e.toString(),e);
			return false;
		}
        return success;
    }
    
    private static  boolean changeWorkingDirectory(String directory,FTPClient ftpClient) throws IOException {
        boolean flag = ftpClient.changeWorkingDirectory(directory);
        if (!flag) {
            log.info("Input Directory {} Error" , directory );
        }
        return flag;
    }
    
  //创建目录
    private static  boolean makeDirectory(String dir,FTPClient ftpClient) throws IOException {
        boolean flag= ftpClient.makeDirectory(dir);
        if (!flag) {
        	log.error("Create Directory {} Error" ,dir);
            
        }
        return flag;
    }

    /**
     * 是否有文件
     * @param path
     * @param ftpClient
     * @return
     * @throws IOException
     */
    private static boolean existFile(String path,FTPClient ftpClient) throws IOException  {
        boolean flag = false;
        FTPFile[] ftpFileArr = ftpClient.listFiles(path);
        if (ftpFileArr.length > 0) {
            flag = true;
        }
        return flag;
    }

}
